package me.chan.netty.rpc.server.handler;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import me.chan.netty.rpc.msg.RpcRequestMessage;
import me.chan.netty.rpc.msg.RpcResponseMessage;

import java.lang.reflect.Method;

@Slf4j
@ChannelHandler.Sharable
public class RpcRequestMessageHandler extends SimpleChannelInboundHandler<RpcRequestMessage> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequestMessage msg) {

        String className = msg.getInterfaceName();
        String methodName = msg.getMethodName();
        Object[] parameterValues = msg.getParameterValues();
        Class[] parameterTypes = msg.getParameterTypes();

        RpcResponseMessage resp = new RpcResponseMessage();
        resp.setSequenceId(resp.getSequenceId());
        try {
            if (className.endsWith("Service"))
                className = className + "Impl";

            Class<?> clazz = Class.forName(className);
            Object obj = clazz.getConstructor().newInstance();
            Method method = obj.getClass().getMethod(methodName, parameterTypes);
            Object ret = method.invoke(obj, parameterValues);
            resp.setReturnValue(ret);
            // int i = 1/0;

        } catch (Exception e) {
            log.error("Exception occurs", e);
            resp.setReturnValue(null);
            resp.setExceptionValue(e.getLocalizedMessage());
        }

        /*catch (ClassNotFoundException | NoSuchMethodException e) {
            log.error("ClassNotFoundException | NoSuchMethodException", e.getMessage());
            resp.setExceptionValue(e.getCause());
        } catch (InvocationTargetException e) {
            log.error("InvocationTargetException", e.getMessage());
            resp.setExceptionValue(e.getCause());
        } catch (InstantiationException e) {
            log.error("InstantiationException", e.getMessage());
            resp.setExceptionValue(e.getCause());
        } catch (IllegalAccessException e) {
            log.error("IllegalAccessException", e.getMessage());
            resp.setExceptionValue(e.getCause());
        }*/

        ctx.writeAndFlush(resp);
    }
}
